home *** CD-ROM | disk | FTP | other *** search
Korn shell script | 1997-08-26 | 4.8 KB | 170 lines |
- #!/bin/ksh
- # @(#) mkdirlist.ksh 2.0 96/01/19
- # 94/10/27 John H. DuBois III (john@armory.com)
- # 94/11/15 Added all options.
- # 94/11/21 Fixed mount option. Added -u to sort options.
- # 95/09/17 Added a option.
- # 96/01/19 Changed default tmpdir to home dir for safety.
- # 96/04/09 Added x option.
-
- # Output format:
- # directory-name full-directory-path
-
- lng_name=${0##*/}
- Usage="Usage: $lng_name [-adhm] [-o<output-file>] [directory|filename ...]"
- Output=$HOME/.dirs
- Mount=-mount
- DoFind=true
- Append=false
- Debug=false
-
- while getopts :ahmdo:x opt; do
- case $opt in
- h)
- echo \
- "$lng_name: make a file of directory names suitable for searching with 'look'.
- The output file contains one line for each directory, with two words on it.
- The first word is the last directory component; the second is the full path to
- the directory (including the last component). The output file is sorted.
- Because the last component is at the start of the line and the lines are
- sorted, the look command can quickly find any directory that begins with a
- given prefix. A file in this format is used by the 'ucd' change-directory
- Korn shell function.
- $Usage
- If a list of directories is given, 'find' is run on them to find all
- directories below them. The -mount flag is included (filesystems mounted
- below the named directories will not be searched). The resulting directory
- list is processed as described above and the output is stored in the output
- file (\"\$HOME/.dirs\" by default; this is where 'ucd' expects to find it).
- If the -d flag is given, the arguments are taken to be files of directory
- lists, one directory name per line (as produced by e.g. 'find / -type d'). If
- -d is given without any command-line arguments, a list of directories is read
- from the standard input. In either case, the directory lists are processed as
- described above and stored in the output file. If one of the input files is
- the same as the output file, it will be read correctly before being
- overwritten.
- Other options:
- -a: Append to the output to the output file, if it already exists.
- -h: Print this help.
- -m: Do not give the -mount flag to find.
- -o<output-file>: Store the output in output-file."
- exit 0
- ;;
- a)
- Append=true
- ;;
- o)
- Output=$OPTARG
- ;;
- m)
- unset Mount
- ;;
- d)
- DoFind=false
- ;;
- x)
- Debug=true
- print -u2 "Debugging is on."
- ;;
- +?)
- print -u2 "$lng_name: options should not be preceded by a '+'."
- exit 1
- ;;
- :)
- print -r -u2 -- \
- "$name: Option '$OPTARG' requires a value. Use -h for help."
- exit 1
- ;;
- ?)
- print -u2 "$lng_name: $OPTARG: bad option. Use -h for help."
- exit 1
- ;;
- esac
- done
-
- # In early ksh, false is an alias and so is not run when a shell var is
- # expanded to it; in these versions unalias false returns 0 so can use this as
- # a test to make it a function instead, which *is* run when expanded from var.
- unalias false && function false { return 1; }
-
- # remove args that were options
- let OPTIND=OPTIND-1
- shift $OPTIND
-
- if [ $# -lt 1 ] && $DoFind; then
- print -u2 "$Usage\nUse -h for help."
- exit
- fi
-
- NZSize=false
-
- : ${TMP:=$TMPDIR}
- : ${TMP:=$HOME}
- : ${TMP:=/tmp}
- if $DoFind; then
- # Catch this because find doesn't care.
- for dir; do
- if [ ! -d "$dir" ]; then
- print -u2 "$lng_name: $dir is not a directory. Aborting."
- exit 1
- fi
- done
- tmpfile=$TMP/#mkdls.$$
- $Debug && set -x
- find "$@" -type d $Mount -print > $tmpfile
- $Debug && set +x
- set -- $tmpfile
- [ -s "$tmpfile" ] && NZSize=true
- else
- for file; do
- $Debug && print -u2 "Checking $file"
- if [ ! -a "$file" ]; then
- print -u2 "$lng_name: cannot access $file. Aborting."
- exit 1
- fi
- # Do this test separately from read because read will fail for
- # empty file.
- if [ ! -r "$file" ]; then
- print -u2 "$lng_name: cannot read $file. Aborting."
- exit 1
- fi
- # This is mainly to make sure that we don't try to reprocess a dir list
- # that is already in the output format.
- read a1 a2 < "$file"
- if [ -n "$a2" ]; then
- print -u2 \
- "$lng_name: $file is not a plain directory list. Aborting."
- exit 1
- fi
- [ -s "$file" ] && NZSize=true
- done
- fi
-
- # Don't overwrite old output file (if any) if we won't put anything in it.
- $NZSize || {
- print -u2 "$lng_name: no directory names to process. Aborting."
- exit 1
- }
-
- PATH=$PATH:/usr/local/bin # make sure we can find gawk
-
- $Append && OtherFiles=$Output || OtherFiles=
-
- # Usage gawk because its %c works the way we want
- gawk -F/ '
- BEGIN {
- for (i = 1; i <= 32; i++)
- BadPat = BadPat sprintf("%c",i)
- BadPat = "[" BadPat sprintf("%c",127) "]"
- }
-
- # Ignore any dirs that have control chars or spaces in them.
- # Control chars are liable to muck up prompt if it includes $PWD,
- # spaces will confuse routines that search/use this file.
- $0 !~ BadPat {
- printf "%s %s\n",$NF,$0
- }
- ' "$@" | sort -u -o $Output - $OtherFiles
-
- $DoFind && rm $tmpfile
-